iT邦幫忙

2023 iThome 鐵人賽

DAY 2
2
AI & Data

從零到英雄:用GCP建立AI交易體系系列 第 2

Day2 標記在股市上的各種眉角

  • 分享至 

  • xImage
  •  

標記(Label)在機器學習中是十分重要的。機器學習中的模型不會平白無故知道你想要他做什麼,你必須要明確告訴模型你的期望,模型才有辦法幫你找到可以擬合的函數。

選擇模型預估的方向

模型的兩大方向分別可以導出兩大標記種類:

  • 數值標記:期望模型可以預測輸出一組數字
    • 原始資料標記:使用原始資料直接進行訓練
    • 轉換資料標記:將資料轉換成另外一種分數用以評估更為抽象的題目,例如輸出的數字代表
  • 類別標記:期望模型輸出一個類別,通常用可能可以用one-hot或是連續的數字進行操作。
    • 二元分類模型:只有兩種類別,通常代表是或否,例如買或不買等等
    • 多分類模型:多種類別,可以包含上漲下跌中立等等不同的狀況。

很多人會直覺反應認為應該使用數值預測的方式,因為這樣可以明確知道未來某時間的成交金額等等。但是這樣有幾個問題以下我們慢慢說明:

  • 雜訊:股市是一個相對複雜而且充滿雜訊的地方,基本上根據金融商品的交易原理一個金融商品必須要經過價格發現才能夠得到公允價格,也就是說會需要藉由不斷買賣來趨近公允價格,而這個過程會產生大量雜訊,導致我們模型會難以收斂。
  • 落後數值:機器學習是一個藉由梯度來調整函數的一個演算法,因此經過實驗會發現模型會一直落後股市反應,形成一個偏移的重影,可以以這個為例,大致會形成以下這張圖,可以看到機器學習預測的曲線轉折都落後時機的線圖:

這樣來看莫非就沒辦法利用AI賺錢錢嗎?
別灰心可以的。我們看到分類方法的部分,分類模型本身因為他是把不同的交易時機給變成類別,你可以把你的問題簡化成漲跌或不漲不跌、買或不買等等的因素,這時候因為就會減少雜訊的出現而可以收斂,並且因為他是"面向決策"的分析模型,所以可以直接輸出使用(買或是賣)。

在今天的Case中,我們就採用分類模型吧!

讓模型做簡單的事

AI不像是人類,通常AI做一件單一、簡單的事情可以做得很好,就像其他不是AI的後端邏輯演算法,但是要AI能夠成為一個"通才"是不容易的。原因是因為AI是在擬合一個現實存在的函數的解,X+1=Y這個函數很簡單,但是當函數複雜起來的時候要找到它的解去擬合就變得十分困難。

股市交易可以拆解成兩件事情組成,漲或跌、買或賣多少(不交易就是0),這兩件事情我們可以將它分開來做。分別訓練一個模型預測漲或跌或中立、另一個模型預測交易或不交易。這樣可以簡化很多問題,讓最後模型的結果可以直接應用到程式中輔助交易。

訓練漲跌的我之後叫他方向標籤、是否交易的叫做交易標籤。因為交易標籤必須要在方向標籤已經有的狀態下才去做討論所以現在先略過。

方向標籤

方向的部分首先可以定義一個時間,讓我們模型預測在這個時間內,交易是否會上漲或下跌到一個程度。因為目前資料是日K線,因此我們可以設定為十個交易日的波段比較合適,經驗上這是一個不長度短的時間。

接著我們要定義一下上漲與下跌要多少才算是有漲或跌而不是只有雜訊在震盪。這裡我提出兩種方法,一個是根據經驗設定一個數值,並且調整數值到上漲、下跌、中立三者數量都相同的狀態,另外一個方法是根據過去幾根K棒的標準差去估計震盪大小,取一倍或兩倍標準差作為上漲或下跌的標準。

這之中分別有一些眉角:

  • 採用固定數值
    • 優點:在訓練上避免標籤偏向造成的梯度下降困難。
    • 缺點:因為設定時會先看所有的資料去調整數值,因此有"訊息洩漏"問題,另外因為採用固定數值,所以也有隨時間變得不是用的問題。
  • 採用標準差
    • 優點:沒有上面的缺點
    • 缺點:會出現標籤偏向導致模型較難訓練

這次我們就先用比較難一些的兩倍標準差作為我們上漲下跌的依據吧。

寫點Code搞定這事情

我們先新增兩個欄位為日期前10日最高價的標準差以及日期前10日最低價的標準差

def compute_rolling_std(series):
    """
    計算給定序列的滾動標準差。
    若資料點不足,則回傳 None。
    """
    if len(series) < 10:
        return [None] * len(series)
    else:
        return series.rolling(window=10).std()

# 為每個股票代碼分別計算滾動標準差
data['前10日最高價標準差'] = data.groupby('股票代號')['最高價'].transform(compute_rolling_std)
data['前10日最低價標準差'] = data.groupby('股票代號')['最低價'].transform(compute_rolling_std)

製作兩個標準差的數值欄位

data['最高價+2倍標準差'] = data['前10日最高價標準差'] * 2 + data['最高價']
data['最低價-2倍標準差'] = data['最低價'] - data['前10日最低價標準差'] * 2

計算label,10日以內只要有一次"最高價"大於"最高價+2倍標準差"則記為1反之為-1都沒有就是0

def rolling_window_labeling_updated(group):
    labels = np.zeros(len(group))
    
    # 找出未來10天的最高價是否大於「最高價+2倍標準差」
    future_max_cond = group['最高價'].rolling(window=10, min_periods=1).max().shift(-10) > group['最高價+2倍標準差']
    # 找出未來10天的最低價是否小於「最低價-2倍標準差」
    future_min_cond = group['最低價'].rolling(window=10, min_periods=1).min().shift(-10) < group['最低價-2倍標準差']
    
    # 標籤滿足最高價條件的資料為1
    labels[future_max_cond] = 1
    # 標籤滿足最低價條件的資料為-1
    labels[future_min_cond] = -1

    # 處理NaN
    nan_mask = group['前10日最高價標準差'].isna() | group['前10日最低價標準差'].isna()
    labels[nan_mask] = np.nan
    
    # 使用 group 的index回傳 Series
    return pd.Series(labels, index=group.index)

# 根據股票代號分組並應用函數
data['label'] = data.groupby('股票代號').apply(rolling_window_labeling_updated).reset_index(level=0, drop=True)
print(data.head(50))

今天先寫到這裡,明天來聊聊特徵建立的部分。

註:

獨熱編碼

可以參考篇文章:連結

價格發現

價格發現是期貨市場上供需雙方公開討價還價,通過激烈競爭,使商品價格水平不斷更新,並且不斷向全世界傳播,從而使該商品價格成為世界價格的過程。簡單地説,價格發現就是發現競爭性價格、世界性價格的過程。
引用自百度


上一篇
Day1 量化交易簡介:資料取得、儲存
下一篇
建立交易模型的下一步:特徵選擇和準備
系列文
從零到英雄:用GCP建立AI交易體系34
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
c5766
iT邦新手 5 級 ‧ 2024-07-15 15:18:02

回報 連結失效

落後數值:機器學習是一個藉由梯度來調整函數的一個演算法,因此經過實驗會發現模型會一直落後股市反應,形成一個偏移的重影,可以以這個為例,大致會形成以下這張圖,可以看到機器學習預測的曲線轉折都落後時機的線圖:

可以以這個為例 這個 連結失效 [2024-07-15 Mon 14:40]

https://ithelp.ithome.com.tw/articles/10318076

我要留言

立即登入留言